package controller

import (
	. "GoAdmin/libs"
	"GoAdmin/models"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"log"
	"net/http"
	"strings"
	"time"
	"xorm.io/builder"
)

var RecordType = map[string]string{
	"2": "classroom",
	"4": "onlineimg",
	"3": "simulation",
}

func UpdateImageAuto(c *gin.Context) {
	json := make(map[string]interface{})
	c.BindJSON(&json)

	taskChan := make(chan *models.File, 2000)
	resultChan := make(chan string, 2000*10)
	taskCount := 0

	for i := 0; i < 100; i++ {
		go worker(taskChan, resultChan)
	}

	endDay := time.Now()
	offsetDur, _ := time.ParseDuration(fmt.Sprintf("%dh", -3*24))
	startDay := endDay.Add(offsetDur)

	startTime := fmt.Sprintf("%s 00:00:00", startDay.Format("2006-01-02"))
	endTime := fmt.Sprintf("%s 23:59:59", endDay.Format("2006-01-02"))

	log.Printf("时间范围: %s - %s", startTime, endTime)

	list, err := new(models.File).CopyFile(startTime, endTime)
	if err != nil {
		log.Panicln("错误: ", err.Error())
	}

	log.Println("任务数: ", len(list))
	taskCount = len(list)
	constTaskCount := taskCount

	go func() {
		for _, dtsFile := range list {
			if dtsFile.Status != "2" {
				log.Printf("#### 注意 #### : 文件ID: %d, 状态: %s 不是2", dtsFile.Id, dtsFile.Status)
			}
			taskChan <- dtsFile
		}
	}()

	for {
		if _, ok := <-resultChan; ok {
			taskCount--
			//log.Println("剩余: ", taskCount, updateResult)
			if taskCount == 0 {
				close(taskChan)
				close(resultChan)
			}
		} else {
			break
		}
	}

	c.JSON(200, gin.H{"msg": fmt.Sprintf("[图片日期更替-自动] [%s 至 %s] 任务总计个数: %d 执行完毕", startTime, endTime, constTaskCount)})

	return
}

func UpdateImage(c *gin.Context) {

}

func RecordFile(c *gin.Context) {
	var (
		data   []*models.FileList
		fileId string
	)
	fileId = c.Query("file_id")
	if fileId == "" {
		c.JSON(201, "不存在")
		return
	}
	filter := builder.NewCond()
	filter = filter.And(builder.Eq{"ld.id": fileId})
	filter = filter.And(builder.Eq{"ld.type": "1"})
	filter = filter.And(builder.Neq{"f.status": "1"})
	data, _ = new(models.File).GetFileList(filter)

	if len(data) == 0 {
		c.JSON(201, "不存在")
		return
	}
	errCount := 0
	for _, v := range data {
		err := RecordPortrait(v)
		log.Println(err)
		if err != nil {
			errCount++
			continue
		}
	}
	c.JSON(200, gin.H{"msg": "处理完成,总共:" + cast.ToString(len(data)) + "条,失败条数:" + cast.ToString(errCount)})
	return
}

func RecordPortrait(fileImage *models.FileList) error {
	time.Sleep(2 * time.Second)
	var (
		patchUrl string
		respMap  map[string]interface{}
		err      error
	)
	data := map[string]interface{}{
		"platnum":   "A0033",
		"stunum":    fileImage.StudentInstitutionCode,
		"devnum":    fileImage.TerminalInstitutionCode,
		"picno":     fileImage.FileNumber,
		"reason":    fileImage.PhotoType,
		"classid":   fileImage.Classid,
		"picurl":    fileImage.FileUrl,
		"size":      3,
		"postime":   fileImage.GnssDatetime.UnixNano() / 1e6,
		"longitude": fileImage.GnssLongitude,
		"latitude":  fileImage.GnssLatitude,
		"alarmflag": fileImage.GnssAlarmflag,
		"stateflag": fileImage.GnssStatus,
		"speed":     fileImage.GnssMaxspeed / 10.0,
		"drispeed":  fileImage.GnssVelocitycar,
		"dir":       fileImage.GnssOritentation,
		"mode":      2,
		"camerach":  0,
	}
	if fileImage.Subject == "1" || fileImage.Subject == "4" {
		if !new(models.File).Edit(fileImage.Id, map[string]interface{}{"status": "1"}) {
			return errors.New("图片上传失败")
		}
		return nil
	} else {
		if fileImage.RecordType != "1" {
			if patchUrl, err = GetSignURL("JsNonCarImageup/"+RecordType[fileImage.RecordType], data, 2, fileImage.Province, fileImage.City); err != nil {
				return err
			}
		} else {
			//log.Println(fileImage.Province, fileImage.City)
			if patchUrl, err = GetSignURL("Jsimageup/image", data, 2, fileImage.Province, fileImage.City); err != nil {
				return err
			}
			//log.Println(patchurl)
		}
	}
	//log.Println(patchurl)
	//log.Println(data)
	respMap = make(map[string]interface{})
	if respMap, err = ApiReq(patchUrl, data, "POST"); err != nil {
		return err
	}
	//log.Println(resp_map["errorcode"], "------------------")
	//log.Println(resp_map["message"], "------------------")
	//武汉市大数据请求
	if fileImage.City == "420100" {
		var wuhanpatchurl string
		if fileImage.RecordType != "1" {
			wuhanpatchurl = "JsNonCarImageup/" + RecordType[fileImage.RecordType]
		} else {
			wuhanpatchurl = "Jsimageup/image"
		}
		if err := WuhanSignReq(wuhanpatchurl, data, 3, fileImage.Province, fileImage.City, "POST"); err != nil {
			err_data := map[string]interface{}{
				"learn_record_id": fileImage.Id,
				"err":             err,
				"data":            data,
			}
			Logfile(err_data, "log.student.log")
		}
	}
	switch respMap["errorcode"].(type) {
	case float64:
		if respMap["errorcode"].(float64) != 0 {
			if strings.Contains(fmt.Sprintf("%s", respMap["message"]), "数据已存在") || strings.Contains(fmt.Sprintf("%s", respMap["message"]), "请勿重复上传") || strings.Contains(fmt.Sprintf("%s", respMap["message"]), "编号重复") {

				if !new(models.File).Edit(fileImage.Id, map[string]interface{}{"status": "1"}) {
					return errors.New("图片上传失败")
				}
				return nil
			}
			if !new(models.File).Edit(fileImage.Id, map[string]interface{}{"status": "2"}) {
				return errors.New("图片上传失败")
			}
			return errors.New(respMap["message"].(string))
			//}
		}
	case string:
		if respMap["errorcode"].(string) != "0" {
			if !new(models.File).Edit(fileImage.Id, map[string]interface{}{"status": "2"}) {
				return errors.New("图片上传失败")
			}
			return errors.New(respMap["message"].(string))
		}
	}
	if !new(models.File).Edit(fileImage.Id, map[string]interface{}{"status": "1"}) {
		return errors.New("图片上传失败")
	}
	return nil
}

func worker(fileChan chan *models.File, resultChan chan string) {
	for {
		if file, ok := <-fileChan; ok {
			if checkWebUrlFileExist(file.FileUrl) {
				resultChan <- fmt.Sprintf(" 成功 文件Id: %d, 状态: %s, 旧: %s 可访问", file.Id, file.Status, file.FileUrl)
				continue
			}

			newURL, err := convertUrlFile(file)
			if err != nil {
				resultChan <- fmt.Sprintf(" 失败 文件Id: %d, 状态: %s, URL 解析失败", file.Id, file.Status)
				continue
			}

			if !checkWebUrlFileExist(newURL) {
				resultChan <- fmt.Sprintf(" 失败 文件Id: %d, 状态: %s, 旧: %s, 新: %s, 新URL不可访问", file.Id, file.Status, file.FileUrl, newURL)
				continue
			}

			err = new(models.File).UpdateFileUrl(file.Id, newURL)
			if err != nil {
				resultChan <- fmt.Sprintf(" 失败 数据库更新 文件Id: %d, 旧: %s, 新: %s", file.Id, file.FileUrl, newURL)
				continue
			}

			resultChan <- fmt.Sprintf(" 成功 文件Id: %d, 旧: %s, 新: %s", file.Id, file.FileUrl, newURL)

		} else {
			break
		}
	}
}

func checkWebUrlFileExist(url string) bool {
	resp, err := http.Head(url)
	if err != nil {
		return false
	}
	if resp.StatusCode != http.StatusOK {
		return false
	}

	return true
}

func convertUrlFile(file *models.File) (string, error) {
	date, err := pickFileUrlDate(file.FileUrl)
	if err != nil {
		return "", err
	}

	newDate := file.AddTime.Format("20060102")
	return strings.Replace(file.FileUrl, date, newDate, 1), nil
}

func pickFileUrlDate(url string) (string, error) {
	index := strings.Index(url, "deviceimgnew")
	if index == -1 {
		return "", fmt.Errorf("url: %s 格式错误")
	}

	return url[index+13 : index+13+8], nil
}
